Introdução

Exploratory data analysis on data from RottenTomatoes about actor Jake Gyllenhaal. The code used to mine the data here analyzed and the explanation on how to use it can be found on this report’s repository deste relatório.

  • Entries that have no infomation about box office were ignored.




Data Overview

import_data("jake_gyllenhaal") 
filmes <- read_imported_data()
filmes %>% 
    glimpse()
Observations: 20
Variables: 5
$ avaliacao  <int> 92, 67, 72, 52, 73, 59, 82, 85, 92, 49, 35, 64, 47, 90, 87, 61, 62, 44, 82, 86
$ filme      <chr> "Stronger", "Life", "Nocturnal Animals", "Demolition", "Everest", "Southpaw", "Prisoners", "End of Watch", "Sour...
$ papel      <chr> "Jeff Bauman", "David Jordan", "Tony HastingsEdward Sheffield", "Davis Mitchell", "Scott Fischer", "Billy \"The ...
$ bilheteria <dbl> 4.2, 30.2, 10.7, 1.7, 46.6, 42.4, 61.0, 39.1, 54.7, 33.3, 90.8, 28.6, 9.7, 33.0, 83.0, 62.6, 7.5, 186.6, 13.8, 4.2
$ ano        <int> 2017, 2017, 2016, 2016, 2015, 2015, 2013, 2012, 2011, 2010, 2010, 2009, 2007, 2007, 2005, 2005, 2005, 2004, 2002...

Box Office

  • Data refers to revenue collected inside the USA.
p <- filmes %>%
    ggplot(aes(x = ano, 
               y = bilheteria,
               text = paste("Movie:",filme,
                            "\nBox Office:",
                            bilheteria,"m",
                            "\nYear:",ano))) + 
    geom_point(size = 4, color = paleta[1]) +
    labs(y = "Box Office (MM)", x = "Year of release")
ggplotly(p, tooltip = "text") %>%
    layout(autosize = F)
  • Among the movies where Jake acted one sets itself apart from others in terms of revenue: The movie “The Day After Tomorrow” released in 2004.

  • It’s possible to notice a downward trend in the Box Office of the movies where Jake acted after 2013.

filmes %>% 
    ggplot(aes(x = bilheteria)) + 
    geom_histogram(aes(y=(..count..)/sum(..count..)),binwidth = 10, boundary = 0, 
                   fill = "grey", color = "black") + 
    geom_rug(size = .5) +
    scale_x_continuous(breaks=seq(0,200,20)) +
    labs(y = "Relative Frequency", x = "Box Office (MM)")

  • We see a clear disparity between “The Day After Tomorrow” and the rest of the movies.

  • No values outside expected domain, e.g. negative values.

p <- filmes %>% 
    ggplot(aes(x = "",
               y = bilheteria,
               label = filme,
               text = paste("Movie:",filme,
                            "\nBox Office:",
                            bilheteria,"m"))) + 
    geom_jitter(width = .05, alpha = .3, size = 3) + 
    labs(x = "", y="Box Office (MM)")
ggplotly(p, tooltip="text") %>% 
    layout(autosize = F)
  • Separate movies in those whose Box Office is below 50 millions and those whose Box Office is above that seems a reasonable approach.

  • “The Day After Tomorrow” seems to form a group of its own. Which would give us 3 groups.

Rating

p <- filmes %>% 
    ggplot(aes(x = ano, 
               y = avaliacao,
                text = paste("Movie:",filme,
                            "\nRating:",
                            avaliacao,
                            "\nYear:",ano))) + 
    geom_point(size = 4, color = paleta[1])  +
    scale_y_continuous(limits = c(0, 100)) +
    labs(y = "Rating RT", x = "Year of Release")
ggplotly(p, tooltip = "text") %>%
    layout(autosize = F)
  • Between 2005 and 2010 Jake participated in a particular series of movies that did not please the critics.
  • There doesn’t seem to exist a particularly clear tendency in the year of release.
filmes %>% 
    ggplot(aes(x = avaliacao)) + 
    geom_histogram(aes(y=(..count..)/sum(..count..)),binwidth = 10, boundary = 0, 
                   fill = paleta[3], color = "black") + 
    geom_rug(size = .5) +
    scale_x_continuous(breaks=seq(0,100,10)) +
    labs(y = "Relative Frequency", x = "Rating RT")

  • It’s possible to notice a considerable number of movies with ratings above 80.

  • No values outside expected domain, e.g. negative values.

p <- filmes %>% 
    ggplot(aes(x = "",
               y = avaliacao,
               text = paste(
                    "Filme:",filme,
                    "\nAvaliação:",avaliacao))) + 
    geom_jitter(width = .05, alpha = .3, size = 3) + 
    labs(x = "", y="Avaliação RT")
ggplotly(p, tooltip = "text") %>% 
    layout(autosize = F)
  • Intuitively three groups arise:
    • The movies with ratings above 80
    • The movies with ratings between 55 and 70
    • The movies with ratings below 55




Hierarchical Clustering



One dimension


Box Office

agrupamento_h = filmes %>% 
    mutate(nome = paste0(filme, " (bil=", bilheteria, ")")) %>% 
    as.data.frame() %>% 
    column_to_rownames("filme") %>% 
    select(bilheteria) %>%
    dist(method = "euclidian") %>% 
    hclust(method = "centroid")
ggdendrogram(agrupamento_h, rotate = T, size = 2, theme_dendro = F) +
    labs(y = "Dissimilarity", x = "", title = "Dendrogram") +
    geom_hline(aes(yintercept = c(20,30), color=c("4 grupos","3 grupos"))) +
    scale_colour_manual(name="#Groups",
    values=c("#56B4E9", "#FF9999"))

  • In terms of Dendrogram the separation in four and three groups seems apropriate, given that the increase in dissimilarity from 4 to 3 groups doesn’t seem to be substantial.
  • Cut made for 4 groups
atribuicoes = get_grupos(agrupamento_h, num_grupos = 1:6)
atribuicoes = atribuicoes %>% 
    left_join(filmes, by = c("label" = "filme"))
atribuicoes %>% 
    ggplot(aes(x = "Movies", y = bilheteria, colour = grupo)) + 
    geom_jitter(width = .02, height = 0, size = 1.6, alpha = .6) + 
    facet_wrap(~ paste(k, " groups")) + 
    scale_color_brewer(palette = "Dark2") +
    labs(y = "Box Office (MM)", x = "", title = "Grouping by Box Office") +
    guides(color=guide_legend(title="group"))

  • The division in 4 groups seems more appropriate than the division in 3 groups.
    • The movie cluster on the base of chart seems to require its own group (In the 4 groups division the aforementioned group would be the group 1).
k_escolhido = 4
m <- list(l = 220)
p <-atribuicoes %>% 
    filter(k == k_escolhido) %>% 
    ggplot(aes(x = reorder(label, bilheteria),
               y = bilheteria,
               colour = grupo,
               text = paste(
                    "Movie:", reorder(label, bilheteria),
                    "\nRating:", bilheteria,
                    "\nGroup:", grupo))) + 
    geom_jitter(width = .02, height = 0, size = 3, alpha = .6) + 
    facet_wrap(~ paste(k, " groups")) + 
    scale_color_brewer(palette = "Dark2") + 
    labs(x = "", y = "Rating RT") + 
    guides(color=guide_legend(title="group")) +
    coord_flip()
ggplotly(p,tooltip = "text") %>%
    layout(autosize = F, margin = m)
  • The Day After Tomorrow demanded a group for itself, as expected.


Rating

agrupamento_h = filmes %>% 
    mutate(nome = paste0(filme, " (av=", avaliacao, ")")) %>% 
    as.data.frame() %>% 
    column_to_rownames("filme") %>% 
    select(avaliacao) %>%
    dist(method = "euclidian") %>% 
    hclust(method = "ward.D")
ggdendrogram(agrupamento_h, rotate = T, size = 2, theme_dendro = F) +
    labs(y = "Dissimilarity", x = "", title = "Dendrogram") +
    geom_hline(aes(yintercept = 30),color="red")

  • In terms of Dendrogram the division in three groups seems the most appropriate, given that the increase in dissimilarity becomes substantial when we go from 3 to 2 groups.
atribuicoes = get_grupos(agrupamento_h, num_grupos = 1:6)
atribuicoes = atribuicoes %>% 
    left_join(filmes, by = c("label" = "filme"))
atribuicoes %>% 
    ggplot(aes(x = "Movies", y = avaliacao, colour = grupo)) + 
    geom_jitter(width = .02, height = 0, size = 1.6, alpha = .6) + 
    facet_wrap(~ paste(k, " groups")) + 
    scale_color_brewer(palette = "Dark2") +
    guides(color=guide_legend(title="group")) +
    labs(y = "Rating RT", x = "", title = "Grouping by Rating")

  • Visually the division in three groups seems appropriate in accordance with the dendrogram.
k_escolhido = 3
m <- list(l = 220)
p <-atribuicoes %>% 
    filter(k == k_escolhido) %>% 
    ggplot(aes(x = reorder(label, avaliacao),
               y = avaliacao,
               colour = grupo,
               text = paste(
                    "Movie:", reorder(label, avaliacao),
                    "\nRating:", avaliacao,
                    "\nGroup:", grupo))) + 
    geom_jitter(width = .02, height = 0, size = 3, alpha = .6) + 
    facet_wrap(~ paste(k, " groups")) + 
    scale_color_brewer(palette = "Dark2") + 
    labs(x = "", y = "Rating RT") + 
    guides(color=guide_legend(title="group")) +
    coord_flip()
ggplotly(p,tooltip = "text") %>%
    layout(autosize = F, margin = m)
  • Arguably, Prince of Persia: The Sands of Time could demand a group of its own.


Two dimensions


How many groups should we choose?


agrupamento_h_2d = filmes %>%
   mutate(bilheteria = log10(bilheteria)) %>%
   mutate_at(vars("avaliacao", "bilheteria"), funs(scale)) %>%
   column_to_rownames("filme") %>%
   select("avaliacao", "bilheteria") %>%
   dist(method = "euclidean") %>%
   hclust(method = "ward.D")
ggdendrogram(agrupamento_h_2d, rotate = TRUE, theme_dendro = F) +
    labs(y = "Dissimilarity", x = "", title = "Dendrogram") +
    geom_hline(aes(yintercept = 4),color="red")

  • Going from 4 to 3 groups represents little variation in terms of dissimilarity
  • Going from 3 to 2 groups represents a relatively substantial increase in dissimilarity, therefore from 6 to 3 groups seems a good choice in terms of dendrogram.
filmes2 <- filmes %>%
    mutate(bilheteria = log10(bilheteria))
plota_hclusts_2d(agrupamento_h_2d,
                filmes2,
                c("avaliacao", "bilheteria"),
                linkage_method = "ward.D", 
                ks = 1:6,
                palette = "Dark2") + 
    facet_wrap(~ paste(k, " groups")) +
    scale_y_log10() +
    guides(color=guide_legend(title="group")) +
    labs(y = "Box Office", x = "Rating", title = "Grouping with two dimensions")

  • The choice of 5 groups seems appropriate, as it reflects matters of Box Office as matters of Ratings. We’ll choose 5 groups for the following reasons (Groups mentioned on the 5 groups divisition):
    • The \(\color{magenta}{\text{4 best rated movies}}\) are very close to each other and suggest a group.
    • The \(\color{#7C3F7C}{\text{3 movies of small Box Office and low ratings}}\) are very dissimilar the rest of the movies and suggest a group.
    • The \(\color{#16A085}{\text{4 movies of small Box Office and high ratings}}\) are close to each other and suggest a group.
    • The \(\color{green}{\text{2 movies of huge Box Office and very low ratings}}\) are very far from the rest of the movies and suggest a group.
    • The \(\color{#CF5300}{\text{6 central/median movies in terms of Box Office/Rating}}\) are very close to each other and suggest a group.
atribuicoes = get_grupos(agrupamento_h_2d, num_grupos = 1:6)
atribuicoes = atribuicoes %>% 
    filter(k == 5) %>%
    mutate(filme = label) %>% 
    left_join(filmes, by = "filme")
p <- atribuicoes %>%
    ggplot(aes(x = avaliacao,
               y = bilheteria,
               colour = grupo,
               text = paste(
                    "Movie:", filme,
                    "\nBox Office:", bilheteria,"m\n",
                    "Rating:", avaliacao))) + 
    geom_jitter(width = .02, height = 0, size = 3, alpha = .6) + 
    facet_wrap(~ paste(k, " groups")) + 
    scale_color_brewer(palette = "Dark2") +
    scale_y_log10() +
    guides(color=guide_legend(title="group")) +
    labs(y = "Box Office", x = "Rating RT")
ggplotly(p, tooltip = "text") %>%
    layout(autosize = F)




What are the name of the groups?


\(\color{#16A085}{\text{Group 1 (Oddball):}}\) Movies overall well received by the public, which reflected on its low revenue. The name Oddball comes from the later interest on the movies from people who consider themselves excentric not rarely to revalidate their sense of exclusivity.


\(\color{#CF5300}{\text{Group 2 (Matinee):}}\) Movies overall not so well received by the critics and more formulaic. In terms of box office most of them had low revenue but the movie paid itself. The name Matinee comes from the idea of that movies that did not perform that well or stopped being the hot topic for a long time occupying being aired by that time.


\(\color{#7C3F7C}{\text{Group 3 (Demolition of a budget):}}\) Movies overall poorly received by both critics and public, which reflected on its small Box Office and low ratings. The name of the group is a wordplay with the very small revenue rendered by the movies, which “demolished” the investment of those who betted in them.


\(\color{magenta}{\text{Grupo 4 (Broke Records and Awards):}}\) Movies acclaimed by critics and whose box office was either successfull or at least decent. The movies in this group have a more serious tone, talking of serious matter that frequently create controversy (serial murders, non heterosexuality, terrorism..). The name of the group is a word play with the name of one of its movies and the sheer amount of prizes this particular movie won.


\(\color{green}{\text{Grupo 5 (BlockBusters):}}\) Movies in which Jack acted that the critics didn’t like that much but who collected a huge box office, with a revenue on the scale of hundreds of millions. The term BlockBuster is usually given to movies who attract crowds to the movie theaters, which is the case of the movies who belong to this group.




Filme-exemplo de cada grupo


\(\color{#16A085}{\text{Grupo 1 (Oddball):}}\)

  • Stronger: Filme biográfico sobre ‘Jeff Bauman’, vítima do atentado de Boston que perdeu ambas as pernas na explosão. O filme foi muito bem recebido pelos críticos que o elogiaram por ser bem executado, comovente e por focar numa história de superação ao invés de usar a tragédia para alimentar a paranóia em cima do terrorismo. O filme porém foi um fracasso em termos de bilheteria.


\(\color{#CF5300}{\text{Grupo 2 (Sessão da Tarde):}}\)

  • Life: Filme no gênero ficção científica espacial, teve um arrecadamento não muito expressivo assim como críticas igualmente pouco entusiasmadas. Foi considerado por muitos bem executados porém pouco inovativo.


\(\color{#7C3F7C}{\text{Grupo 3 (Demolition of a budget):}}\)

  • Demolition: Neste filme Jake atua no papel de um homem que volta ao trabalho depois de perder a esposa e encontra contato humano em uma atendente de telemarketing ao reclamar de uma vending machine. O filme foi um fracasso em termos de arrecadamento assim como em termos de crítica. O filme teve seu script apontado como grande problema, esse foi descrito como ‘tentando afetar profundidade’ e anti-carismático.


\(\color{magenta}{\text{Grupo 4 (Broke Records and Awards):}}\)

  • Brokeback Mountain: Provavelmente a melhor atuação de Jake Gyllenhaal até o momento, esse filme rendeu a Jake uma indicação ao Oscar e levantou muita controvérsia por conter uma cena de sexo entre pessoas do mesmo sexo. A Academia (responsável por escolher os vencedores do Oscar) foi acusada de homofobia por não escolher esse filme como o ganhador de Melhor Fotografia, ainda assim Brokeback Mountain ganhou outros 141 prêmios e 128 nominações de acordo com o IMDB. O filme foi considerado um sucesso tanto em faturamento como em avaliação.


\(\color{green}{\text{Grupo 5 (BlockBusters):}}\)

  • Prince of Persia: The Sands of Time: Baseado no jogo de mesmo nome, jogo que ainda é pra muitos uma referência em qualidade e inovação. O filme resultou em comentários decepcionados tanto de críticos e fãs, os quais curiosamente não falharam em contribuir pro arrecadamento do filme.
LS0tCnRpdGxlOiAiSmFrZSBHeWxsZW5oYWFsJ3MgdHlwZSBvZiBtb3ZpZXMiCmF1dGhvcjogIkpvc8OpIEJlbmFyZGkgZGUgU291emEgTnVuZXMiCmRhdGU6ICIyMi8wNS8yMDE4IgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazoKICAgIHRvYzogeWVzCiAgICB0b2NfZmxvYXQ6IHllcwogIGh0bWxfZG9jdW1lbnQ6CiAgICBkZl9wcmludDogcGFnZWQKICAgIHRvYzogeWVzCiAgICB0b2NfZmxvYXQ6IHllcwotLS0KCjxici8+PGJyLz4KCiMgSW50cm9kdcOnw6NvCgo+IEV4cGxvcmF0b3J5IGRhdGEgYW5hbHlzaXMgb24gZGF0YSBmcm9tIFtSb3R0ZW5Ub21hdG9lc10oaHR0cHM6Ly93d3cucm90dGVudG9tYXRvZXMuY29tLykgYWJvdXQgYWN0b3IgSmFrZSBHeWxsZW5oYWFsLiBUaGUgY29kZSB1c2VkIHRvIG1pbmUgdGhlIGRhdGEgaGVyZSBhbmFseXplZCBhbmQgdGhlIGV4cGxhbmF0aW9uIG9uIGhvdyB0byB1c2UgaXQgY2FuIGJlIGZvdW5kIG9uIFt0aGlzIHJlcG9ydCdzIHJlcG9zaXRvcnldKGh0dHBzOi8vZ2l0aHViLmNvbS9CZW5hcmRpL2FncnVwYW1lbnRvLWZpbG1lcy8pIGRlc3RlIHJlbGF0w7NyaW8uCgoqIEVudHJpZXMgdGhhdCBoYXZlIG5vIGluZm9tYXRpb24gYWJvdXQgYm94IG9mZmljZSB3ZXJlIGlnbm9yZWQuCgo8YnI+CgoqKioKCjxicj4KCmBgYHtyIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGhlcmUpCmxpYnJhcnkoY2x1c3RlcikKbGlicmFyeShwbG90bHkpCmxpYnJhcnkoZ2dkZW5kcm8pCgpzb3VyY2UoaGVyZTo6aGVyZSgiY29kZS9saWIuUiIpKQpzb3VyY2UoaGVyZTo6aGVyZSgiY29kZS9wbG90YV9zb2x1Y29lc19oY2x1c3QuUiIpKQoKdGhlbWVfc2V0KHRoZW1lX3JlcG9ydCgpKQoKa25pdHI6Om9wdHNfY2h1bmskc2V0KHRpZHkgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgIGZpZy53aWR0aCA9IDYsCiAgICAgICAgICAgICAgICAgICAgICBmaWcuaGVpZ2h0ID0gNSwKICAgICAgICAgICAgICAgICAgICAgIGVjaG8gPSBUUlVFKQpwYWxldGEgPSBjKCIjNDA0RTREIiwKICAgICAgICAgICAiIzkyRENFNSIsCiAgICAgICAgICAgIiM5MzhCQTEiLAogICAgICAgICAgICIjMkQzMTQyIiwKICAgICAgICAgICAiI0Y0NzQzQiIpCnNldC5zZWVkKDEwMSkKYGBgCgojIERhdGEgT3ZlcnZpZXcKCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmltcG9ydF9kYXRhKCJqYWtlX2d5bGxlbmhhYWwiKSAKZmlsbWVzIDwtIHJlYWRfaW1wb3J0ZWRfZGF0YSgpCmZpbG1lcyAlPiUgCiAgICBnbGltcHNlKCkKYGBgCgojIyBCb3ggT2ZmaWNlCgoqIERhdGEgcmVmZXJzIHRvIHJldmVudWUgY29sbGVjdGVkIGluc2lkZSB0aGUgVVNBLgoKYGBge3J9CnAgPC0gZmlsbWVzICU+JQogICAgZ2dwbG90KGFlcyh4ID0gYW5vLCAKICAgICAgICAgICAgICAgeSA9IGJpbGhldGVyaWEsCiAgICAgICAgICAgICAgIHRleHQgPSBwYXN0ZSgiTW92aWU6IixmaWxtZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICJcbkJveCBPZmZpY2U6IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJpbGhldGVyaWEsIm0iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIlxuWWVhcjoiLGFubykpKSArIAogICAgZ2VvbV9wb2ludChzaXplID0gNCwgY29sb3IgPSBwYWxldGFbMV0pICsKICAgIGxhYnMoeSA9ICJCb3ggT2ZmaWNlIChNTSkiLCB4ID0gIlllYXIgb2YgcmVsZWFzZSIpCgpnZ3Bsb3RseShwLCB0b29sdGlwID0gInRleHQiKSAlPiUKICAgIGxheW91dChhdXRvc2l6ZSA9IEYpCmBgYAoKKiBBbW9uZyB0aGUgbW92aWVzIHdoZXJlIEpha2UgYWN0ZWQgb25lIHNldHMgaXRzZWxmIGFwYXJ0IGZyb20gb3RoZXJzIGluIHRlcm1zIG9mIHJldmVudWU6IFRoZSBtb3ZpZSAqKiJUaGUgRGF5IEFmdGVyIFRvbW9ycm93IioqIHJlbGVhc2VkIGluIDIwMDQuCgoqIEl0J3MgcG9zc2libGUgdG8gbm90aWNlIGEgZG93bndhcmQgdHJlbmQgaW4gdGhlIEJveCBPZmZpY2Ugb2YgdGhlIG1vdmllcyB3aGVyZSBKYWtlIGFjdGVkIGFmdGVyIDIwMTMuICAKCmBgYHtyfQpmaWxtZXMgJT4lIAogICAgZ2dwbG90KGFlcyh4ID0gYmlsaGV0ZXJpYSkpICsgCiAgICBnZW9tX2hpc3RvZ3JhbShhZXMoeT0oLi5jb3VudC4uKS9zdW0oLi5jb3VudC4uKSksYmlud2lkdGggPSAxMCwgYm91bmRhcnkgPSAwLCAKICAgICAgICAgICAgICAgICAgIGZpbGwgPSAiZ3JleSIsIGNvbG9yID0gImJsYWNrIikgKyAKICAgIGdlb21fcnVnKHNpemUgPSAuNSkgKwogICAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcz1zZXEoMCwyMDAsMjApKSArCiAgICBsYWJzKHkgPSAiUmVsYXRpdmUgRnJlcXVlbmN5IiwgeCA9ICJCb3ggT2ZmaWNlIChNTSkiKQpgYGAKCiogV2Ugc2VlIGEgY2xlYXIgZGlzcGFyaXR5IGJldHdlZW4gKioiVGhlIERheSBBZnRlciBUb21vcnJvdyIqKiBhbmQgdGhlIHJlc3Qgb2YgdGhlIG1vdmllcy4KCiogTm8gdmFsdWVzIG91dHNpZGUgZXhwZWN0ZWQgZG9tYWluLCBlLmcuIG5lZ2F0aXZlIHZhbHVlcy4KCmBgYHtyfQpwIDwtIGZpbG1lcyAlPiUgCiAgICBnZ3Bsb3QoYWVzKHggPSAiIiwKICAgICAgICAgICAgICAgeSA9IGJpbGhldGVyaWEsCiAgICAgICAgICAgICAgIGxhYmVsID0gZmlsbWUsCiAgICAgICAgICAgICAgIHRleHQgPSBwYXN0ZSgiTW92aWU6IixmaWxtZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICJcbkJveCBPZmZpY2U6IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJpbGhldGVyaWEsIm0iKSkpICsgCiAgICBnZW9tX2ppdHRlcih3aWR0aCA9IC4wNSwgYWxwaGEgPSAuMywgc2l6ZSA9IDMpICsgCiAgICBsYWJzKHggPSAiIiwgeT0iQm94IE9mZmljZSAoTU0pIikKCmdncGxvdGx5KHAsIHRvb2x0aXA9InRleHQiKSAlPiUgCiAgICBsYXlvdXQoYXV0b3NpemUgPSBGKQpgYGAKCiogU2VwYXJhdGUgbW92aWVzIGluIHRob3NlIHdob3NlIEJveCBPZmZpY2UgaXMgYmVsb3cgNTAgbWlsbGlvbnMgYW5kIHRob3NlIHdob3NlIEJveCBPZmZpY2UgaXMgYWJvdmUgdGhhdCBzZWVtcyBhIHJlYXNvbmFibGUgYXBwcm9hY2guIAoKKiAqKiJUaGUgRGF5IEFmdGVyIFRvbW9ycm93IioqIHNlZW1zIHRvIGZvcm0gYSBncm91cCBvZiBpdHMgb3duLiBXaGljaCB3b3VsZCBnaXZlIHVzIDMgZ3JvdXBzLgoKIyMgUmF0aW5nCgpgYGB7cn0KcCA8LSBmaWxtZXMgJT4lIAogICAgZ2dwbG90KGFlcyh4ID0gYW5vLCAKICAgICAgICAgICAgICAgeSA9IGF2YWxpYWNhbywKICAgICAgICAgICAgICAgIHRleHQgPSBwYXN0ZSgiTW92aWU6IixmaWxtZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICJcblJhdGluZzoiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgYXZhbGlhY2FvLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIlxuWWVhcjoiLGFubykpKSArIAogICAgZ2VvbV9wb2ludChzaXplID0gNCwgY29sb3IgPSBwYWxldGFbMV0pICArCiAgICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAxMDApKSArCiAgICBsYWJzKHkgPSAiUmF0aW5nIFJUIiwgeCA9ICJZZWFyIG9mIFJlbGVhc2UiKQoKZ2dwbG90bHkocCwgdG9vbHRpcCA9ICJ0ZXh0IikgJT4lCiAgICBsYXlvdXQoYXV0b3NpemUgPSBGKQpgYGAKCiogQmV0d2VlbiAyMDA1IGFuZCAyMDEwIEpha2UgcGFydGljaXBhdGVkIGluIGEgcGFydGljdWxhciBzZXJpZXMgb2YgbW92aWVzIHRoYXQgZGlkIG5vdCBwbGVhc2UgdGhlIGNyaXRpY3MuIAoqIFRoZXJlIGRvZXNuJ3Qgc2VlbSB0byBleGlzdCBhIHBhcnRpY3VsYXJseSBjbGVhciB0ZW5kZW5jeSBpbiB0aGUgeWVhciBvZiByZWxlYXNlLiAKCmBgYHtyfQpmaWxtZXMgJT4lIAogICAgZ2dwbG90KGFlcyh4ID0gYXZhbGlhY2FvKSkgKyAKICAgIGdlb21faGlzdG9ncmFtKGFlcyh5PSguLmNvdW50Li4pL3N1bSguLmNvdW50Li4pKSxiaW53aWR0aCA9IDEwLCBib3VuZGFyeSA9IDAsIAogICAgICAgICAgICAgICAgICAgZmlsbCA9IHBhbGV0YVszXSwgY29sb3IgPSAiYmxhY2siKSArIAogICAgZ2VvbV9ydWcoc2l6ZSA9IC41KSArCiAgICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzPXNlcSgwLDEwMCwxMCkpICsKICAgIGxhYnMoeSA9ICJSZWxhdGl2ZSBGcmVxdWVuY3kiLCB4ID0gIlJhdGluZyBSVCIpCmBgYAoKKiBJdCdzIHBvc3NpYmxlIHRvIG5vdGljZSBhIGNvbnNpZGVyYWJsZSBudW1iZXIgb2YgbW92aWVzIHdpdGggcmF0aW5ncyBhYm92ZSA4MC4KCiogTm8gdmFsdWVzIG91dHNpZGUgZXhwZWN0ZWQgZG9tYWluLCBlLmcuIG5lZ2F0aXZlIHZhbHVlcy4KCmBgYHtyfQpwIDwtIGZpbG1lcyAlPiUgCiAgICBnZ3Bsb3QoYWVzKHggPSAiIiwKICAgICAgICAgICAgICAgeSA9IGF2YWxpYWNhbywKICAgICAgICAgICAgICAgdGV4dCA9IHBhc3RlKAogICAgICAgICAgICAgICAgICAgICJGaWxtZToiLGZpbG1lLAogICAgICAgICAgICAgICAgICAgICJcbkF2YWxpYcOnw6NvOiIsYXZhbGlhY2FvKSkpICsgCiAgICBnZW9tX2ppdHRlcih3aWR0aCA9IC4wNSwgYWxwaGEgPSAuMywgc2l6ZSA9IDMpICsgCiAgICBsYWJzKHggPSAiIiwgeT0iQXZhbGlhw6fDo28gUlQiKQoKZ2dwbG90bHkocCwgdG9vbHRpcCA9ICJ0ZXh0IikgJT4lIAogICAgbGF5b3V0KGF1dG9zaXplID0gRikKCmBgYAoKKiBJbnR1aXRpdmVseSB0aHJlZSBncm91cHMgYXJpc2U6CiAgICAqIFRoZSBtb3ZpZXMgd2l0aCByYXRpbmdzIGFib3ZlIDgwCiAgICAqIFRoZSBtb3ZpZXMgd2l0aCByYXRpbmdzIGJldHdlZW4gNTUgYW5kIDcwIAogICAgKiBUaGUgbW92aWVzIHdpdGggcmF0aW5ncyBiZWxvdyA1NQoKPGJyPgoKKioqCgo8YnI+CgojIEhpZXJhcmNoaWNhbCBDbHVzdGVyaW5nCgo8YnI+Cjxicj4KCiMjIE9uZSBkaW1lbnNpb24KCjxicj4KCiMjIyBCb3ggT2ZmaWNlCgpgYGB7cn0KYWdydXBhbWVudG9faCA9IGZpbG1lcyAlPiUgCiAgICBtdXRhdGUobm9tZSA9IHBhc3RlMChmaWxtZSwgIiAoYmlsPSIsIGJpbGhldGVyaWEsICIpIikpICU+JSAKICAgIGFzLmRhdGEuZnJhbWUoKSAlPiUgCiAgICBjb2x1bW5fdG9fcm93bmFtZXMoImZpbG1lIikgJT4lIAogICAgc2VsZWN0KGJpbGhldGVyaWEpICU+JQogICAgZGlzdChtZXRob2QgPSAiZXVjbGlkaWFuIikgJT4lIAogICAgaGNsdXN0KG1ldGhvZCA9ICJjZW50cm9pZCIpCgpnZ2RlbmRyb2dyYW0oYWdydXBhbWVudG9faCwgcm90YXRlID0gVCwgc2l6ZSA9IDIsIHRoZW1lX2RlbmRybyA9IEYpICsKICAgIGxhYnMoeSA9ICJEaXNzaW1pbGFyaXR5IiwgeCA9ICIiLCB0aXRsZSA9ICJEZW5kcm9ncmFtIikgKwogICAgZ2VvbV9obGluZShhZXMoeWludGVyY2VwdCA9IGMoMjAsMzApLCBjb2xvcj1jKCI0IGdydXBvcyIsIjMgZ3J1cG9zIikpKSArCiAgICBzY2FsZV9jb2xvdXJfbWFudWFsKG5hbWU9IiNHcm91cHMiLAogICAgdmFsdWVzPWMoIiM1NkI0RTkiLCAiI0ZGOTk5OSIpKQpgYGAKCiogSW4gdGVybXMgb2YgRGVuZHJvZ3JhbSB0aGUgc2VwYXJhdGlvbiBpbiBmb3VyIGFuZCB0aHJlZSBncm91cHMgc2VlbXMgYXByb3ByaWF0ZSwgZ2l2ZW4gdGhhdCB0aGUgaW5jcmVhc2UgaW4gZGlzc2ltaWxhcml0eSBmcm9tIDQgdG8gMyBncm91cHMgZG9lc24ndCBzZWVtIHRvIGJlIHN1YnN0YW50aWFsLgoqIEN1dCBtYWRlIGZvciA0IGdyb3VwcwoKYGBge3J9CmF0cmlidWljb2VzID0gZ2V0X2dydXBvcyhhZ3J1cGFtZW50b19oLCBudW1fZ3J1cG9zID0gMTo2KQoKYXRyaWJ1aWNvZXMgPSBhdHJpYnVpY29lcyAlPiUgCiAgICBsZWZ0X2pvaW4oZmlsbWVzLCBieSA9IGMoImxhYmVsIiA9ICJmaWxtZSIpKQoKYXRyaWJ1aWNvZXMgJT4lIAogICAgZ2dwbG90KGFlcyh4ID0gIk1vdmllcyIsIHkgPSBiaWxoZXRlcmlhLCBjb2xvdXIgPSBncnVwbykpICsgCiAgICBnZW9tX2ppdHRlcih3aWR0aCA9IC4wMiwgaGVpZ2h0ID0gMCwgc2l6ZSA9IDEuNiwgYWxwaGEgPSAuNikgKyAKICAgIGZhY2V0X3dyYXAofiBwYXN0ZShrLCAiIGdyb3VwcyIpKSArIAogICAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAiRGFyazIiKSArCiAgICBsYWJzKHkgPSAiQm94IE9mZmljZSAoTU0pIiwgeCA9ICIiLCB0aXRsZSA9ICJHcm91cGluZyBieSBCb3ggT2ZmaWNlIikgKwogICAgZ3VpZGVzKGNvbG9yPWd1aWRlX2xlZ2VuZCh0aXRsZT0iZ3JvdXAiKSkKYGBgCgoqIFRoZSBkaXZpc2lvbiBpbiA0IGdyb3VwcyBzZWVtcyBtb3JlIGFwcHJvcHJpYXRlIHRoYW4gdGhlIGRpdmlzaW9uIGluIDMgZ3JvdXBzLgogICAgKiBUaGUgbW92aWUgY2x1c3RlciBvbiB0aGUgYmFzZSBvZiBjaGFydCBzZWVtcyB0byByZXF1aXJlIGl0cyBvd24gZ3JvdXAgKEluIHRoZSA0IGdyb3VwcyBkaXZpc2lvbiB0aGUgYWZvcmVtZW50aW9uZWQgZ3JvdXAgd291bGQgYmUgdGhlIGdyb3VwIDEpLgoKYGBge3J9CmtfZXNjb2xoaWRvID0gNAoKbSA8LSBsaXN0KGwgPSAyMjApCgpwIDwtYXRyaWJ1aWNvZXMgJT4lIAogICAgZmlsdGVyKGsgPT0ga19lc2NvbGhpZG8pICU+JSAKICAgIGdncGxvdChhZXMoeCA9IHJlb3JkZXIobGFiZWwsIGJpbGhldGVyaWEpLAogICAgICAgICAgICAgICB5ID0gYmlsaGV0ZXJpYSwKICAgICAgICAgICAgICAgY29sb3VyID0gZ3J1cG8sCiAgICAgICAgICAgICAgIHRleHQgPSBwYXN0ZSgKICAgICAgICAgICAgICAgICAgICAiTW92aWU6IiwgcmVvcmRlcihsYWJlbCwgYmlsaGV0ZXJpYSksCiAgICAgICAgICAgICAgICAgICAgIlxuUmF0aW5nOiIsIGJpbGhldGVyaWEsCiAgICAgICAgICAgICAgICAgICAgIlxuR3JvdXA6IiwgZ3J1cG8pKSkgKyAKICAgIGdlb21faml0dGVyKHdpZHRoID0gLjAyLCBoZWlnaHQgPSAwLCBzaXplID0gMywgYWxwaGEgPSAuNikgKyAKICAgIGZhY2V0X3dyYXAofiBwYXN0ZShrLCAiIGdyb3VwcyIpKSArIAogICAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAiRGFyazIiKSArIAogICAgbGFicyh4ID0gIiIsIHkgPSAiUmF0aW5nIFJUIikgKyAKICAgIGd1aWRlcyhjb2xvcj1ndWlkZV9sZWdlbmQodGl0bGU9Imdyb3VwIikpICsKICAgIGNvb3JkX2ZsaXAoKQoKZ2dwbG90bHkocCx0b29sdGlwID0gInRleHQiKSAlPiUKICAgIGxheW91dChhdXRvc2l6ZSA9IEYsIG1hcmdpbiA9IG0pCgpgYGAKCiogKipUaGUgRGF5IEFmdGVyIFRvbW9ycm93KiogZGVtYW5kZWQgYSBncm91cCBmb3IgaXRzZWxmLCBhcyBleHBlY3RlZC4KCjxicj4KCiMjIyBSYXRpbmcgCgpgYGB7cn0KYWdydXBhbWVudG9faCA9IGZpbG1lcyAlPiUgCiAgICBtdXRhdGUobm9tZSA9IHBhc3RlMChmaWxtZSwgIiAoYXY9IiwgYXZhbGlhY2FvLCAiKSIpKSAlPiUgCiAgICBhcy5kYXRhLmZyYW1lKCkgJT4lIAogICAgY29sdW1uX3RvX3Jvd25hbWVzKCJmaWxtZSIpICU+JSAKICAgIHNlbGVjdChhdmFsaWFjYW8pICU+JQogICAgZGlzdChtZXRob2QgPSAiZXVjbGlkaWFuIikgJT4lIAogICAgaGNsdXN0KG1ldGhvZCA9ICJ3YXJkLkQiKQoKZ2dkZW5kcm9ncmFtKGFncnVwYW1lbnRvX2gsIHJvdGF0ZSA9IFQsIHNpemUgPSAyLCB0aGVtZV9kZW5kcm8gPSBGKSArCiAgICBsYWJzKHkgPSAiRGlzc2ltaWxhcml0eSIsIHggPSAiIiwgdGl0bGUgPSAiRGVuZHJvZ3JhbSIpICsKICAgIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSAzMCksY29sb3I9InJlZCIpCmBgYAoKKiBJbiB0ZXJtcyBvZiBEZW5kcm9ncmFtIHRoZSAqKmRpdmlzaW9uIGluIHRocmVlIGdyb3VwcyBzZWVtcyB0aGUgbW9zdCBhcHByb3ByaWF0ZSoqLCBnaXZlbiB0aGF0IHRoZSBpbmNyZWFzZSBpbiBkaXNzaW1pbGFyaXR5IGJlY29tZXMgc3Vic3RhbnRpYWwgd2hlbiB3ZSBnbyBmcm9tIDMgdG8gMiBncm91cHMuCgpgYGB7cn0KYXRyaWJ1aWNvZXMgPSBnZXRfZ3J1cG9zKGFncnVwYW1lbnRvX2gsIG51bV9ncnVwb3MgPSAxOjYpCgphdHJpYnVpY29lcyA9IGF0cmlidWljb2VzICU+JSAKICAgIGxlZnRfam9pbihmaWxtZXMsIGJ5ID0gYygibGFiZWwiID0gImZpbG1lIikpCgphdHJpYnVpY29lcyAlPiUgCiAgICBnZ3Bsb3QoYWVzKHggPSAiTW92aWVzIiwgeSA9IGF2YWxpYWNhbywgY29sb3VyID0gZ3J1cG8pKSArIAogICAgZ2VvbV9qaXR0ZXIod2lkdGggPSAuMDIsIGhlaWdodCA9IDAsIHNpemUgPSAxLjYsIGFscGhhID0gLjYpICsgCiAgICBmYWNldF93cmFwKH4gcGFzdGUoaywgIiBncm91cHMiKSkgKyAKICAgIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlID0gIkRhcmsyIikgKwogICAgZ3VpZGVzKGNvbG9yPWd1aWRlX2xlZ2VuZCh0aXRsZT0iZ3JvdXAiKSkgKwogICAgbGFicyh5ID0gIlJhdGluZyBSVCIsIHggPSAiIiwgdGl0bGUgPSAiR3JvdXBpbmcgYnkgUmF0aW5nIikKCmBgYAoKKiBWaXN1YWxseSB0aGUgZGl2aXNpb24gaW4gdGhyZWUgZ3JvdXBzIHNlZW1zIGFwcHJvcHJpYXRlIGluIGFjY29yZGFuY2Ugd2l0aCB0aGUgZGVuZHJvZ3JhbS4KCmBgYHtyfQprX2VzY29saGlkbyA9IDMKCm0gPC0gbGlzdChsID0gMjIwKQoKcCA8LWF0cmlidWljb2VzICU+JSAKICAgIGZpbHRlcihrID09IGtfZXNjb2xoaWRvKSAlPiUgCiAgICBnZ3Bsb3QoYWVzKHggPSByZW9yZGVyKGxhYmVsLCBhdmFsaWFjYW8pLAogICAgICAgICAgICAgICB5ID0gYXZhbGlhY2FvLAogICAgICAgICAgICAgICBjb2xvdXIgPSBncnVwbywKICAgICAgICAgICAgICAgdGV4dCA9IHBhc3RlKAogICAgICAgICAgICAgICAgICAgICJNb3ZpZToiLCByZW9yZGVyKGxhYmVsLCBhdmFsaWFjYW8pLAogICAgICAgICAgICAgICAgICAgICJcblJhdGluZzoiLCBhdmFsaWFjYW8sCiAgICAgICAgICAgICAgICAgICAgIlxuR3JvdXA6IiwgZ3J1cG8pKSkgKyAKICAgIGdlb21faml0dGVyKHdpZHRoID0gLjAyLCBoZWlnaHQgPSAwLCBzaXplID0gMywgYWxwaGEgPSAuNikgKyAKICAgIGZhY2V0X3dyYXAofiBwYXN0ZShrLCAiIGdyb3VwcyIpKSArIAogICAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAiRGFyazIiKSArIAogICAgbGFicyh4ID0gIiIsIHkgPSAiUmF0aW5nIFJUIikgKyAKICAgIGd1aWRlcyhjb2xvcj1ndWlkZV9sZWdlbmQodGl0bGU9Imdyb3VwIikpICsKICAgIGNvb3JkX2ZsaXAoKQoKZ2dwbG90bHkocCx0b29sdGlwID0gInRleHQiKSAlPiUKICAgIGxheW91dChhdXRvc2l6ZSA9IEYsIG1hcmdpbiA9IG0pCgpgYGAKCiogQXJndWFibHksICoqUHJpbmNlIG9mIFBlcnNpYTogVGhlIFNhbmRzIG9mIFRpbWUqKiBjb3VsZCBkZW1hbmQgYSBncm91cCBvZiBpdHMgb3duLgoKPGJyPgoKIyMgVHdvIGRpbWVuc2lvbnMKCjxicj4KCiMjIyBIb3cgbWFueSBncm91cHMgc2hvdWxkIHdlIGNob29zZT8gCgo8YnI+CgpgYGB7ciwgd2FybmluZz1GQUxTRX0KYWdydXBhbWVudG9faF8yZCA9IGZpbG1lcyAlPiUKICAgbXV0YXRlKGJpbGhldGVyaWEgPSBsb2cxMChiaWxoZXRlcmlhKSkgJT4lCiAgIG11dGF0ZV9hdCh2YXJzKCJhdmFsaWFjYW8iLCAiYmlsaGV0ZXJpYSIpLCBmdW5zKHNjYWxlKSkgJT4lCiAgIGNvbHVtbl90b19yb3duYW1lcygiZmlsbWUiKSAlPiUKICAgc2VsZWN0KCJhdmFsaWFjYW8iLCAiYmlsaGV0ZXJpYSIpICU+JQogICBkaXN0KG1ldGhvZCA9ICJldWNsaWRlYW4iKSAlPiUKICAgaGNsdXN0KG1ldGhvZCA9ICJ3YXJkLkQiKQoKZ2dkZW5kcm9ncmFtKGFncnVwYW1lbnRvX2hfMmQsIHJvdGF0ZSA9IFRSVUUsIHRoZW1lX2RlbmRybyA9IEYpICsKICAgIGxhYnMoeSA9ICJEaXNzaW1pbGFyaXR5IiwgeCA9ICIiLCB0aXRsZSA9ICJEZW5kcm9ncmFtIikgKwogICAgZ2VvbV9obGluZShhZXMoeWludGVyY2VwdCA9IDQpLGNvbG9yPSJyZWQiKQoKYGBgCgoqIEdvaW5nIGZyb20gNCB0byAzIGdyb3VwcyByZXByZXNlbnRzIGxpdHRsZSB2YXJpYXRpb24gaW4gdGVybXMgb2YgZGlzc2ltaWxhcml0eQoqIEdvaW5nIGZyb20gMyB0byAyIGdyb3VwcyByZXByZXNlbnRzIGEgcmVsYXRpdmVseSBzdWJzdGFudGlhbCBpbmNyZWFzZSBpbiBkaXNzaW1pbGFyaXR5LCB0aGVyZWZvcmUgZnJvbSA2IHRvIDMgZ3JvdXBzIHNlZW1zIGEgZ29vZCBjaG9pY2UgaW4gdGVybXMgb2YgZGVuZHJvZ3JhbS4KCmBgYHtyfQpmaWxtZXMyIDwtIGZpbG1lcyAlPiUKICAgIG11dGF0ZShiaWxoZXRlcmlhID0gbG9nMTAoYmlsaGV0ZXJpYSkpCgpwbG90YV9oY2x1c3RzXzJkKGFncnVwYW1lbnRvX2hfMmQsCiAgICAgICAgICAgICAgICBmaWxtZXMyLAogICAgICAgICAgICAgICAgYygiYXZhbGlhY2FvIiwgImJpbGhldGVyaWEiKSwKICAgICAgICAgICAgICAgIGxpbmthZ2VfbWV0aG9kID0gIndhcmQuRCIsIAogICAgICAgICAgICAgICAga3MgPSAxOjYsCiAgICAgICAgICAgICAgICBwYWxldHRlID0gIkRhcmsyIikgKyAKICAgIGZhY2V0X3dyYXAofiBwYXN0ZShrLCAiIGdyb3VwcyIpKSArCiAgICBzY2FsZV95X2xvZzEwKCkgKwogICAgZ3VpZGVzKGNvbG9yPWd1aWRlX2xlZ2VuZCh0aXRsZT0iZ3JvdXAiKSkgKwogICAgbGFicyh5ID0gIkJveCBPZmZpY2UiLCB4ID0gIlJhdGluZyIsIHRpdGxlID0gIkdyb3VwaW5nIHdpdGggdHdvIGRpbWVuc2lvbnMiKQpgYGAKCiogVGhlIGNob2ljZSBvZiA1IGdyb3VwcyBzZWVtcyBhcHByb3ByaWF0ZSwgYXMgaXQgcmVmbGVjdHMgbWF0dGVycyBvZiBCb3ggT2ZmaWNlIGFzIG1hdHRlcnMgb2YgUmF0aW5ncy4gKipXZSdsbCBjaG9vc2UgNSBncm91cHMqKiBmb3IgdGhlIGZvbGxvd2luZyByZWFzb25zIChHcm91cHMgbWVudGlvbmVkIG9uIHRoZSA1IGdyb3VwcyBkaXZpc2l0aW9uKTogCiAgICAqIFRoZSAkXGNvbG9ye21hZ2VudGF9e1x0ZXh0ezQgYmVzdCByYXRlZCBtb3ZpZXN9fSQgYXJlIHZlcnkgY2xvc2UgdG8gZWFjaCBvdGhlciBhbmQgc3VnZ2VzdCBhIGdyb3VwLgogICAgKiBUaGUgJFxjb2xvcnsjN0MzRjdDfXtcdGV4dHszIG1vdmllcyBvZiBzbWFsbCBCb3ggT2ZmaWNlIGFuZCBsb3cgcmF0aW5nc319JCBhcmUgdmVyeSBkaXNzaW1pbGFyIHRoZSByZXN0IG9mIHRoZSBtb3ZpZXMgYW5kIHN1Z2dlc3QgYSBncm91cC4KICAgICogVGhlICRcY29sb3J7IzE2QTA4NX17XHRleHR7NCBtb3ZpZXMgb2Ygc21hbGwgQm94IE9mZmljZSBhbmQgaGlnaCByYXRpbmdzfX0kIGFyZSBjbG9zZSB0byBlYWNoIG90aGVyIGFuZCBzdWdnZXN0IGEgZ3JvdXAuCiAgICAqIFRoZSAkXGNvbG9ye2dyZWVufXtcdGV4dHsyIG1vdmllcyBvZiBodWdlIEJveCBPZmZpY2UgYW5kIHZlcnkgbG93IHJhdGluZ3N9fSQgYXJlIHZlcnkgZmFyIGZyb20gdGhlIHJlc3Qgb2YgdGhlIG1vdmllcyBhbmQgc3VnZ2VzdCBhIGdyb3VwLgogICAgKiBUaGUgJFxjb2xvcnsjQ0Y1MzAwfXtcdGV4dHs2IGNlbnRyYWwvbWVkaWFuIG1vdmllcyBpbiB0ZXJtcyBvZiBCb3ggT2ZmaWNlL1JhdGluZ319JCBhcmUgdmVyeSBjbG9zZSB0byBlYWNoIG90aGVyIGFuZCBzdWdnZXN0IGEgZ3JvdXAuCgpgYGB7cn0KYXRyaWJ1aWNvZXMgPSBnZXRfZ3J1cG9zKGFncnVwYW1lbnRvX2hfMmQsIG51bV9ncnVwb3MgPSAxOjYpCgphdHJpYnVpY29lcyA9IGF0cmlidWljb2VzICU+JSAKICAgIGZpbHRlcihrID09IDUpICU+JQogICAgbXV0YXRlKGZpbG1lID0gbGFiZWwpICU+JSAKICAgIGxlZnRfam9pbihmaWxtZXMsIGJ5ID0gImZpbG1lIikKCnAgPC0gYXRyaWJ1aWNvZXMgJT4lCiAgICBnZ3Bsb3QoYWVzKHggPSBhdmFsaWFjYW8sCiAgICAgICAgICAgICAgIHkgPSBiaWxoZXRlcmlhLAogICAgICAgICAgICAgICBjb2xvdXIgPSBncnVwbywKICAgICAgICAgICAgICAgdGV4dCA9IHBhc3RlKAogICAgICAgICAgICAgICAgICAgICJNb3ZpZToiLCBmaWxtZSwKICAgICAgICAgICAgICAgICAgICAiXG5Cb3ggT2ZmaWNlOiIsIGJpbGhldGVyaWEsIm1cbiIsCiAgICAgICAgICAgICAgICAgICAgIlJhdGluZzoiLCBhdmFsaWFjYW8pKSkgKyAKICAgIGdlb21faml0dGVyKHdpZHRoID0gLjAyLCBoZWlnaHQgPSAwLCBzaXplID0gMywgYWxwaGEgPSAuNikgKyAKICAgIGZhY2V0X3dyYXAofiBwYXN0ZShrLCAiIGdyb3VwcyIpKSArIAogICAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAiRGFyazIiKSArCiAgICBzY2FsZV95X2xvZzEwKCkgKwogICAgZ3VpZGVzKGNvbG9yPWd1aWRlX2xlZ2VuZCh0aXRsZT0iZ3JvdXAiKSkgKwogICAgbGFicyh5ID0gIkJveCBPZmZpY2UiLCB4ID0gIlJhdGluZyBSVCIpCgoKZ2dwbG90bHkocCwgdG9vbHRpcCA9ICJ0ZXh0IikgJT4lCiAgICBsYXlvdXQoYXV0b3NpemUgPSBGKQpgYGAKCjxicj4KCioqKgoKPGJyPgoKIyMjIFdoYXQgYXJlIHRoZSBuYW1lIG9mIHRoZSBncm91cHM/IAoKPGJyPgoKJFxjb2xvcnsjMTZBMDg1fXtcdGV4dHtHcm91cCAxIChPZGRiYWxsKTp9fSQgX01vdmllcyBvdmVyYWxsIHdlbGwgcmVjZWl2ZWQgYnkgdGhlIHB1YmxpY18sIHdoaWNoIHJlZmxlY3RlZCBvbiBpdHMgbG93IHJldmVudWUuIFRoZSBuYW1lIE9kZGJhbGwgY29tZXMgZnJvbSB0aGUgbGF0ZXIgaW50ZXJlc3Qgb24gdGhlIG1vdmllcyBmcm9tIHBlb3BsZSB3aG8gY29uc2lkZXIgdGhlbXNlbHZlcyBleGNlbnRyaWMgbm90IHJhcmVseSB0byByZXZhbGlkYXRlIHRoZWlyIHNlbnNlIG9mIGV4Y2x1c2l2aXR5LgoKPGJyLz4KCiRcY29sb3J7I0NGNTMwMH17XHRleHR7R3JvdXAgMiAoTWF0aW5lZSk6fX0kIE1vdmllcyBvdmVyYWxsIF9ub3Qgc28gd2VsbCByZWNlaXZlZCBieSB0aGUgY3JpdGljcyBhbmQgbW9yZSBmb3JtdWxhaWNfLiBJbiB0ZXJtcyBvZiBib3ggb2ZmaWNlIG1vc3Qgb2YgdGhlbSBoYWQgbG93IHJldmVudWUgYnV0IHRoZSBtb3ZpZSBwYWlkIGl0c2VsZi4gVGhlIG5hbWUgTWF0aW5lZSBjb21lcyBmcm9tIHRoZSBpZGVhIG9mIHRoYXQgbW92aWVzIHRoYXQgZGlkIG5vdCBwZXJmb3JtIHRoYXQgd2VsbCBvciBzdG9wcGVkIGJlaW5nIHRoZSBob3QgdG9waWMgZm9yIGEgbG9uZyB0aW1lIG9jY3VweWluZyBiZWluZyBhaXJlZCBieSB0aGF0IHRpbWUuCgo8YnIvPgoKJFxjb2xvcnsjN0MzRjdDfXtcdGV4dHtHcm91cCAzIChEZW1vbGl0aW9uIG9mIGEgYnVkZ2V0KTp9fSQgTW92aWVzIG92ZXJhbGwgX3Bvb3JseSByZWNlaXZlZCBieSBib3RoIGNyaXRpY3MgYW5kIHB1YmxpY18sIHdoaWNoIHJlZmxlY3RlZCBvbiBpdHMgc21hbGwgQm94IE9mZmljZSBhbmQgbG93IHJhdGluZ3MuIFRoZSBuYW1lIG9mIHRoZSBncm91cCBpcyBhIHdvcmRwbGF5IHdpdGggdGhlIHZlcnkgc21hbGwgcmV2ZW51ZSByZW5kZXJlZCBieSB0aGUgbW92aWVzLCB3aGljaCAiZGVtb2xpc2hlZCIgdGhlIGludmVzdG1lbnQgb2YgdGhvc2Ugd2hvIGJldHRlZCBpbiB0aGVtLiAKCjxici8+CgokXGNvbG9ye21hZ2VudGF9e1x0ZXh0e0dydXBvIDQgKEJyb2tlIFJlY29yZHMgYW5kIEF3YXJkcyk6fX0kIE1vdmllcyBfYWNjbGFpbWVkIGJ5IGNyaXRpY3NfIGFuZCB3aG9zZSBib3ggb2ZmaWNlIHdhcyBlaXRoZXIgc3VjY2Vzc2Z1bGwgb3IgYXQgbGVhc3QgZGVjZW50LiBUaGUgbW92aWVzIGluIHRoaXMgZ3JvdXAgaGF2ZSBhIG1vcmUgc2VyaW91cyB0b25lLCB0YWxraW5nIG9mIHNlcmlvdXMgbWF0dGVyIHRoYXQgZnJlcXVlbnRseSBjcmVhdGUgY29udHJvdmVyc3kgKHNlcmlhbCBtdXJkZXJzLCBub24gaGV0ZXJvc2V4dWFsaXR5LCB0ZXJyb3Jpc20uLikuIFRoZSBuYW1lIG9mIHRoZSBncm91cCBpcyBhIHdvcmQgcGxheSB3aXRoIHRoZSBuYW1lIG9mIG9uZSBvZiBpdHMgbW92aWVzIGFuZCB0aGUgc2hlZXIgYW1vdW50IG9mIHByaXplcyB0aGlzIHBhcnRpY3VsYXIgbW92aWUgd29uLiAKCjxici8+CgokXGNvbG9ye2dyZWVufXtcdGV4dHtHcnVwbyA1IChCbG9ja0J1c3RlcnMpOn19JCBNb3ZpZXMgaW4gd2hpY2ggSmFjayBhY3RlZCB0aGF0IHRoZSBjcml0aWNzIGRpZG4ndCBsaWtlIHRoYXQgbXVjaCBidXQgd2hvIGNvbGxlY3RlZCBhIGh1Z2UgYm94IG9mZmljZSwgd2l0aCBhIHJldmVudWUgb24gdGhlIHNjYWxlIG9mIGh1bmRyZWRzIG9mIG1pbGxpb25zLiBUaGUgdGVybSBCbG9ja0J1c3RlciBpcyB1c3VhbGx5IGdpdmVuIHRvIG1vdmllcyB3aG8gYXR0cmFjdCBjcm93ZHMgdG8gdGhlIG1vdmllIHRoZWF0ZXJzLCB3aGljaCBpcyB0aGUgY2FzZSBvZiB0aGUgbW92aWVzIHdobyBiZWxvbmcgdG8gdGhpcyBncm91cC4KCjxicj4KCioqKgoKPGJyLz4KCiMjIyBGaWxtZS1leGVtcGxvIGRlIGNhZGEgZ3J1cG8gIAoKPGJyLz4KCiRcY29sb3J7IzE2QTA4NX17XHRleHR7R3J1cG8gMSAoT2RkYmFsbCk6fX0kCgoqICoqU3Ryb25nZXIqKjogRmlsbWUgYmlvZ3LDoWZpY28gc29icmUgJ0plZmYgQmF1bWFuJywgdsOtdGltYSBkbyBhdGVudGFkbyBkZSBCb3N0b24gcXVlIHBlcmRldSBhbWJhcyBhcyBwZXJuYXMgbmEgZXhwbG9zw6NvLiBPIGZpbG1lIGZvaSBtdWl0byBiZW0gcmVjZWJpZG8gcGVsb3MgY3LDrXRpY29zIHF1ZSBvIGVsb2dpYXJhbSBwb3Igc2VyIGJlbSBleGVjdXRhZG8sIGNvbW92ZW50ZSBlIHBvciBmb2NhciBudW1hIGhpc3TDs3JpYSBkZSBzdXBlcmHDp8OjbyBhbyBpbnbDqXMgZGUgdXNhciBhIHRyYWfDqWRpYSBwYXJhIGFsaW1lbnRhciBhIHBhcmFuw7NpYSBlbSBjaW1hIGRvIHRlcnJvcmlzbW8uIE8gZmlsbWUgcG9yw6ltIGZvaSB1bSBmcmFjYXNzbyBlbSB0ZXJtb3MgZGUgYmlsaGV0ZXJpYS4KCjxici8+CgokXGNvbG9yeyNDRjUzMDB9e1x0ZXh0e0dydXBvIDIgKFNlc3PDo28gZGEgVGFyZGUpOn19JAoKKiAqKkxpZmUqKjogRmlsbWUgbm8gZ8OqbmVybyBmaWPDp8OjbyBjaWVudMOtZmljYSBlc3BhY2lhbCwgdGV2ZSB1bSBhcnJlY2FkYW1lbnRvIG7Do28gbXVpdG8gZXhwcmVzc2l2bwphc3NpbSBjb21vIGNyw610aWNhcyBpZ3VhbG1lbnRlIHBvdWNvIGVudHVzaWFzbWFkYXMuIEZvaSBjb25zaWRlcmFkbyBwb3IgbXVpdG9zIGJlbSBleGVjdXRhZG9zIHBvcsOpbSBwb3VjbyBpbm92YXRpdm8uCgo8YnIvPgoKJFxjb2xvcnsjN0MzRjdDfXtcdGV4dHtHcnVwbyAzIChEZW1vbGl0aW9uIG9mIGEgYnVkZ2V0KTp9fSQgCgoqICoqRGVtb2xpdGlvbioqOiBOZXN0ZSBmaWxtZSBKYWtlIGF0dWEgbm8gcGFwZWwgZGUgdW0gaG9tZW0gcXVlIHZvbHRhIGFvIHRyYWJhbGhvIGRlcG9pcyBkZSBwZXJkZXIgYSBlc3Bvc2EgZSBlbmNvbnRyYSBjb250YXRvIGh1bWFubyBlbSB1bWEgYXRlbmRlbnRlIGRlIHRlbGVtYXJrZXRpbmcgYW8gcmVjbGFtYXIgZGUgdW1hIHZlbmRpbmcgbWFjaGluZS4gTyBmaWxtZSBmb2kgdW0gZnJhY2Fzc28gZW0gdGVybW9zIGRlIGFycmVjYWRhbWVudG8gYXNzaW0gY29tbyBlbSB0ZXJtb3MgZGUgY3LDrXRpY2EuIE8gZmlsbWUgdGV2ZSBzZXUgc2NyaXB0IGFwb250YWRvIGNvbW8gZ3JhbmRlIHByb2JsZW1hLCBlc3NlIGZvaSBkZXNjcml0byBjb21vICd0ZW50YW5kbyBhZmV0YXIgcHJvZnVuZGlkYWRlJyBlIGFudGktY2FyaXNtw6F0aWNvLgogICAgCjxici8+CgokXGNvbG9ye21hZ2VudGF9e1x0ZXh0e0dydXBvIDQgKEJyb2tlIFJlY29yZHMgYW5kIEF3YXJkcyk6fX0kCgoqICoqQnJva2ViYWNrIE1vdW50YWluKio6IFByb3ZhdmVsbWVudGUgYSBtZWxob3IgYXR1YcOnw6NvIGRlIEpha2UgR3lsbGVuaGFhbCBhdMOpIG8gbW9tZW50bywgZXNzZSBmaWxtZSByZW5kZXUgYSBKYWtlIHVtYSBpbmRpY2HDp8OjbyBhbyBPc2NhciBlIGxldmFudG91IG11aXRhIGNvbnRyb3bDqXJzaWEgcG9yIGNvbnRlciB1bWEgY2VuYSBkZSBzZXhvIGVudHJlIHBlc3NvYXMgZG8gbWVzbW8gc2V4by4gQSBBY2FkZW1pYSAocmVzcG9uc8OhdmVsIHBvciBlc2NvbGhlciBvcyB2ZW5jZWRvcmVzIGRvIE9zY2FyKSBmb2kgYWN1c2FkYSBkZSBob21vZm9iaWEgcG9yIG7Do28gZXNjb2xoZXIgZXNzZSBmaWxtZSBjb21vIG8gZ2FuaGFkb3IgZGUgTWVsaG9yIEZvdG9ncmFmaWEsIGFpbmRhIGFzc2ltIEJyb2tlYmFjayBNb3VudGFpbiBnYW5ob3Ugb3V0cm9zIDE0MSBwcsOqbWlvcyBlIDEyOCBub21pbmHDp8O1ZXMgZGUgYWNvcmRvIGNvbSBvIElNREIuIE8gZmlsbWUgZm9pIGNvbnNpZGVyYWRvIHVtIHN1Y2Vzc28gdGFudG8gZW0gZmF0dXJhbWVudG8gY29tbyBlbSBhdmFsaWHDp8Ojby4KCjxici8+CgokXGNvbG9ye2dyZWVufXtcdGV4dHtHcnVwbyA1IChCbG9ja0J1c3RlcnMpOn19JCAKCiogKipQcmluY2Ugb2YgUGVyc2lhOiBUaGUgU2FuZHMgb2YgVGltZSoqOiBCYXNlYWRvIG5vIGpvZ28gZGUgbWVzbW8gbm9tZSwgam9nbyBxdWUgYWluZGEgw6kgcHJhIG11aXRvcyB1bWEgcmVmZXLDqm5jaWEgZW0gcXVhbGlkYWRlIGUgaW5vdmHDp8Ojby4gTyBmaWxtZSByZXN1bHRvdSBlbSBjb21lbnTDoXJpb3MgZGVjZXBjaW9uYWRvcyB0YW50byBkZSBjcsOtdGljb3MgZSBmw6NzLCBvcyBxdWFpcyBjdXJpb3NhbWVudGUgbsOjbyBmYWxoYXJhbSBlbSBjb250cmlidWlyIHBybyBhcnJlY2FkYW1lbnRvIGRvIGZpbG1lLgogICAgCg==